import { Component, Input, OnInit } from '@angular/core';
import { _HttpClient, DrawerHelper, ModalHelper } from '@delon/theme';
import { deepMergeKey } from '@delon/util';

import { STColumn, STColumnButton, STConfig, STData } from '@delon/abc';
import { filter } from 'rxjs/operators';
export interface TreeNodeInterface {
  key: string;
  name: string;
  menuType: number;
  icon: string;
  url: string;
  sortNo: number;
  expand: boolean;
  children?: TreeNodeInterface[];
}
@Component({
  selector: 'app-tree-table',
  templateUrl: `./index.html`,
  styleUrls: ['./index.less']
})
export class TreeTableComponent implements OnInit {
  listOfMapData = [];
  @Input()
  data;
  @Input()
  columns: STColumn[];
  private copyCog: STConfig;
  mapOfExpandedData: { [key: string]: TreeNodeInterface[] } = {};

  constructor(
    private http: _HttpClient,
    private modalHelper: ModalHelper,
    private drawerHelper: DrawerHelper,
    private cog: STConfig,
  ) {
    this.copyCog = deepMergeKey(new STConfig(), true, cog);
    delete this.copyCog.multiSort;
    Object.assign(this, this.copyCog);
  }

  ngOnInit() {
    this.load();
  }


  collapse(array: TreeNodeInterface[], data: TreeNodeInterface, $event: boolean): void {
    if ($event === false) {
      if (data.children) {
        data.children.forEach(d => {
          const target = array.find(a => a.key === d.key)!;
          target.expand = false;
          this.collapse(array, target, false);
        });
      } else {
        return;
      }
    }
  }

  convertTreeToList(root: object): TreeNodeInterface[] {
    const stack: any[] = [];
    const array: any[] = [];
    const hashMap = {};
    stack.push({...root, level: 0, expand: false});

    while (stack.length !== 0) {
      const node = stack.pop();
      this.visitNode(node, hashMap, array);
      if (node.children) {
        for (let i = node.children.length - 1; i >= 0; i--) {
          stack.push({...node.children[i], level: node.level + 1, expand: false, parent: node});
        }
      }
    }

    return array;
  }

  visitNode(node: TreeNodeInterface, hashMap: { [key: string]: any }, array: TreeNodeInterface[]): void {
    if (!hashMap[node.key]) {
      hashMap[node.key] = true;
      array.push(node);
    }
  }
  _btnClick(record: STData, btn: STColumnButton) {
    if (btn.type === 'modal' || btn.type === 'static') {
      const { modal } = btn;
      const obj = { [modal!.paramsName!]: record };
      (this.modalHelper[btn.type === 'modal' ? 'create' : 'createStatic'] as any)(
        modal!.component,
        { ...obj, ...(modal!.params && modal!.params!(record)) },
        deepMergeKey({}, true, this.copyCog.modal, modal),
      )
        .pipe(filter(w => typeof w !== 'undefined'))
        .subscribe(res => this.btnCallback(record, btn, res));
      return;
    } else if (btn.type === 'drawer') {
      const { drawer } = btn;
      const obj = { [drawer!.paramsName!]: record };
      this.drawerHelper
        .create(
          drawer!.title!,
          drawer!.component,
          { ...obj, ...(drawer!.params && drawer!.params!(record)) },
          deepMergeKey({}, true, this.copyCog.drawer, drawer),
        )
        .pipe(filter(w => typeof w !== 'undefined'))
        .subscribe(res => this.btnCallback(record, btn, res));
      return;
    }
    this.btnCallback(record, btn);
  }

  private btnCallback(record: STData, btn: STColumnButton, modal?: any) {
    if (!btn.click) return;
    if (typeof btn.click === 'string') {
      switch (btn.click) {
        case 'load':
          this.load();
          break;
        case 'reload':
          this.reload();
          break;
      }
    } else {
      return btn.click(record, modal);
    }
  }
  _btnText(record: STData, btn: STColumnButton) {
    // tslint:disable-next-line: deprecation
    if (btn.format) {
      // tslint:disable-next-line: deprecation
      return btn.format(record, btn);
    }
    return typeof btn.text === 'function' ? btn.text : btn.text || '';
  }
  public load() {
    this.http.get(this.data).subscribe((res: any) => {
      this.listOfMapData = res.result;
      this.listOfMapData.forEach(item => {
        this.mapOfExpandedData[item.key] = this.convertTreeToList(item);
      });
    });
  }

  public reload() {
    this.load();
  }
}
